#include "Tetrahedron.h"
#ifdef __APPLE__
    #include <OpenGL/gl.h>
#else
    #include <GL/gl.h>
#endif
#include <QVector3D>

QVector4D QVector4DfromArray(float* v)
{
    return QVector4D(v[0],v[1],v[2], v[3]);
}

QVector3D QVector3DfromArray(float* v)
{
    return QVector3D(v[0],v[1],v[2]);
}

Tetrahedron::Tetrahedron(const QVector3D& center, QObject *parent):
    Object3D(center, parent)
{
    setInputType(GL_TRIANGLES);
    constroiFaces();
}

Tetrahedron::Tetrahedron(const Tetrahedron& tt): Object3D(tt)
{
    constroiFaces();
}

Object3D* Tetrahedron::copy() const
{
    return new Tetrahedron(*this);
}

Tetrahedron::~Tetrahedron()
{
}

void buildNormal(TRIANGLE& t)
{
    QVector3D v1 = t.v[1].toVector3DAffine() - t.v[0].toVector3DAffine();
    QVector3D v2 = t.v[2].toVector3DAffine() - t.v[0].toVector3DAffine();
    t.n = QVector3D::crossProduct(v1,v2);
    t.n.normalize();
}

void Tetrahedron::beforeDraw()
{
    QMatrix4x4 mVM = modelViewMatrix();

    mI = 0;
    float mC = -2000.0;
    for(int i = 0; i < 4; ++i)
    {
        TRIANGLE t;
        for(int j = 0; j < 3; ++j) t.v[j] = mVM * faces[i].v[j];
        buildNormal(t);

        if(t.n.z() > mC)
        {

            mC = t.n.z();
            mI = i;
        }
        faces[i].color = QVector4D(1.0,1.0,1.0,1.0);
    }
    faces[mI].color = QVector4D(1.0,1.0,0.0,1.0);
}

void Tetrahedron::drawGeometry(void)
{
    beforeDraw();
    glBegin(GL_TRIANGLES);
    {
        for(int i = 0; i < 4; ++i)
        {
            glColor3fv(reinterpret_cast<const GLfloat *>(&(faces[i].color)));
            glNormal3fv(reinterpret_cast<const GLfloat *>(&(faces[i].n)));
            for(int j = 0; j < 3; ++j)
                glVertex4fv(reinterpret_cast<const GLfloat *>(&(faces[i].v[j])));
        }
    }glEnd();
}

TRIANGLE Tetrahedron::getTrianguloFrente()
{
    return faces[mI];
}

#define BET01(val) ((val >= 0.0 && val <= 1.0)? true: false)

bool Tetrahedron::dentro(const QVector4D& p)
{
    QMatrix4x4 Q;
    Q.setColumn(0,v0);
    Q.setColumn(1,v1);
    Q.setColumn(2,v2);
    Q.setColumn(3,v3);

    QVector4D bar = Q.inverted()*p;
    return BET01(bar.x()) && BET01(bar.y()) && BET01(bar.z()) && BET01(bar.w());
}

void Tetrahedron::constroiFaces()
{
    float v[16] = { -1.0, -1.0, -1.0, 1.0,
                     1.0,  1.0, -1.0, 1.0,
                     1.0, -1.0,  1.0, 1.0,
                    -1.0,  1.0,  1.0, 1.0};

    v0 = QVector4DfromArray(&v[4*0]);
    v1 = QVector4DfromArray(&v[4*1]);
    v2 = QVector4DfromArray(&v[4*2]);
    v3 = QVector4DfromArray(&v[4*3]);

    //Face 1
    faces[0].v[0] = QVector4DfromArray(&v[4*1]);
    faces[0].v[1] = QVector4DfromArray(&v[4*3]);
    faces[0].v[2] = QVector4DfromArray(&v[4*2]);
    faces[0].color = QVector4D(1.0,1.0,1.0,1.0);
    faces[0].n = (-QVector3DfromArray(&v[4*0])).normalized();

    //Face 2
    faces[1].v[0] = QVector4DfromArray(&v[4*1]);
    faces[1].v[1] = QVector4DfromArray(&v[4*2]);
    faces[1].v[2] = QVector4DfromArray(&v[4*0]);
    faces[1].color = QVector4D(1.0,1.0,1.0,1.0);
    faces[1].n = (-QVector3DfromArray(&v[4*3])).normalized();

    //Face 3
    faces[2].v[0] = QVector4DfromArray(&v[4*1]);
    faces[2].v[1] = QVector4DfromArray(&v[4*0]);
    faces[2].v[2] = QVector4DfromArray(&v[4*3]);
    faces[2].color = QVector4D(1.0,1.0,1.0,1.0);
    faces[2].n = (-QVector3DfromArray(&v[4*2])).normalized();

    //Face 4
    faces[3].v[0] = QVector4DfromArray(&v[4*0]);
    faces[3].v[1] = QVector4DfromArray(&v[4*2]);
    faces[3].v[2] = QVector4DfromArray(&v[4*3]);
    faces[3].color = QVector4D(1.0,1.0,1.0,1.0);
    faces[3].n = (-QVector3DfromArray(&v[4*1])).normalized();
}
